## Warning in scpcaTools::add_miQC(filtered_sce): prob_compromised was already
## calculated and will be replaced.
## Warning in miQC::mixtureModel(sce): Unable to identify two distributions. Use plotMetrics function
##                 to confirm assumptions of miQC are met.
## Warning in miQC::mixtureModel(sce): Unable to identify two distributions. Use plotMetrics function
##                 to confirm assumptions of miQC are met.
## Warning in miQC::mixtureModel(sce): Unable to identify two distributions. Use plotMetrics function
##                 to confirm assumptions of miQC are met.

Metadata and Processing Information for SCPCL000040

Sample Metadata

The below table summarizes clinical metadata for the sample associated with this library. Blue hyperlinks are present for any terms with an ontology term identifier associated with the displayed human readable value. These links will direct you to a web page with information about that ontology term identifier.

Sample ID SCPCS000040
Diagnosis Pilocytic astrocytoma
Subdiagnosis NA
Tissue location Thalamic
Disease timing Initial diagnosis
Age 11
Sex F
Organism Homo sapiens
Sample type patient tissue

Raw Library Metrics

Library id SCPCL000040
Sample id SCPCS000040
Tech version 10Xv3
Data modalities RNA-seq
Cells reported by alevin-fry 86,048
Number of genes assayed 60,319
Number of RNA-seq reads sequenced 132,649,146
Percent of RNA-seq reads mapped to transcripts 27.38%

Pre-Processing Information

Salmon version 1.5.2
Alevin-fry version 0.7.0
Transcriptome index Homo_sapiens.GRCh38.104.spliced_intron.txome
Alevin-fry droplet detection unfiltered
Resolution CellRangerLikeEm
Transcripts included Total and spliced only

RNA-seq Experiment Summary

Cell Statistics

Method used to filter empty droplets emptyDropsCellRanger
Number of cells post filtering empty droplets 5,909
Percent of reads in cells 88.4%
Median UMI count per cell 581
Median genes detected per cell 492
Median percent reads mitochondrial 6%
Method used to filter low quality cells Minimum_gene_cutoff
Cells after filtering low quality cells 5,874
Normalization method deconvolution
Minimum genes per cell cutoff 200

Knee Plot

Smoothed knee plot of filtered and unfiltered droplets

The total UMI count of each droplet (barcode) plotted against the rank of that droplet allows visualization of the distribution of sequencing depth across droplets. The droplets that are expected to contain cells were identified with DropletUtils::emptyDropsCellRanger(), unless otherwise specified in the Cell Statistics table, which uses both the total UMI counts and expressed gene content (adapted from Lun et al. 2019). As the boundary between droplets passing and failing this filter is not solely dependent on total UMI count, some regions contain droplets in both categories. The color in this plot indicates the percentage of droplets in a region passing the filter.

Cell Read Metrics

Total UMI x genes expressed

The above plot of cell metrics includes only droplets which have passed the emptyDropsCellRanger() filter. The plot will usually display a strong (but curved) relationship between the total UMI count and the number of genes detected. Cells with low UMI counts and high mitochondrial percentages may require further filtering.

miQC Model Diagnostics

miQC model diagnostics plot

We calculate the probability that a cell is compromised due to degradation or rupture using miQC (Hippen et al. 2021). This relies on fitting a mixture model using the number of genes expressed by a cell and the percentage of mitochondrial reads. The expected plot will show a characteristic triangular shape and two model fit lines. Cells with low numbers of genes expressed may have both low and high mitochondrial percentage, but cells with many genes tend to have a low mitochondrial percentage. Compromised cells are likely to have a fewer genes detected and higher percentage of mitochondrial reads.

If the model has failed to fit properly, the pattern of cells may differ, and there may not be model fit lines. This can be the result of a low-quality library or may occur if there is no mitochondrial content, as in the case of a high-quality single-nucleus sample. In such situations, the calculated probability of compromise may not be valid (see miQC vignette for more details).

Removing low quality cells

The below plot highlights cells that were removed prior to normalization and dimensionality reduction. Cells that should be removed based on RNA counts are those that are identified to be low quality cells, such as cells with high probability of being compromised. The method of filtering is indicated above the plot as either miQC or Minimum gene cutoff. If miQC, cells below the specified probability compromised cutoff and above the minimum number of unique genes identified are kept for downstream analyses. If only a Minimum gene cutoff is used, then miQC is not used and only those cells that pass the minimum number of unique genes identified threshold are retained. The dotted vertical line indicates the minimum gene cutoff used for filtering.

The raw counts from all cells that remain after filtering low quality cells (RNA only) are then normalized prior to selection of highly variable genes and dimensionality reduction.

Dimensionality Reduction

The below plot shows the UMAP (Uniform Manifold Approximation and Projection) embeddings for each cell, coloring each cell by the total number of genes detected per cell.

Expression of highly variable genes

The plots below show the same UMAP embeddings, coloring each cell by the expression level of the labeled gene. The genes chosen for plotting are the 12 most variable genes identified in the library. Gene symbols are used when available to label the UMAP plots. If gene symbols are not available, the Ensembl id will be shown.

Cell type Annotation Summary

The plots and tables included here detail the results from performing cell type annotation.

This library contains the following cell type annotations:

  • SingleR
  • CellAssign

For additional information about cell typing, including methods used for cell typing, information about reference sources, comparisons among cell type annotation methods, and diagnostic plots, please refer to the supplementary cell type QC report.

Statistics

SingleR cell type annotations

In this table, cells labeled “Unknown cell type” are those which SingleR pruned due to low-quality assignments. In the processed result files, these cells are labeled NA.
Annotated cell type Number of cells Percent of cells
CD4-positive, alpha-beta T cell 1551 26.4%
central memory CD8-positive, alpha-beta T cell 972 16.55%
common lymphoid progenitor 540 9.19%
central memory CD4-positive, alpha-beta T cell 536 9.12%
regulatory T cell 486 8.27%
effector memory CD8-positive, alpha-beta T cell 370 6.3%
dendritic cell 250 4.26%
CD8-positive, alpha-beta T cell 203 3.46%
plasma cell 161 2.74%
natural killer cell 157 2.67%
effector memory CD4-positive, alpha-beta T cell 156 2.66%
megakaryocyte-erythroid progenitor cell 120 2.04%
granulocyte monocyte progenitor cell 102 1.74%
hematopoietic stem cell 91 1.55%
hematopoietic multipotent progenitor cell 62 1.06%
erythrocyte 44 0.75%
neuron 29 0.49%
megakaryocyte 7 0.12%
class switched memory B cell 6 0.1%
keratinocyte 6 0.1%
melanocyte 5 0.09%
memory B cell 3 0.05%
naive B cell 3 0.05%
epithelial cell 2 0.03%
inflammatory macrophage 2 0.03%
microvascular endothelial cell 2 0.03%
monocyte 2 0.03%
common myeloid progenitor 1 0.02%
fat cell 1 0.02%
macrophage 1 0.02%
Unknown cell type 3 0.05%

CellAssign cell type annotations

In this table, cells labeled “Unknown cell type” are those which CellAssign could not confidently assign to a label in the reference list. In the processed result files, these cells are labeled "other".
Annotated cell type Number of cells Percent of cells
T helper cells 56 0.95%
T cells 42 0.72%
Nuocytes 12 0.2%
Microglia 9 0.15%
T regulatory cells 9 0.15%
Oligodendrocyte progenitor cells 6 0.1%
Monocytes 2 0.03%
Dendritic cells 1 0.02%
Endothelial cells (aorta) 1 0.02%
GABAergic neurons 1 0.02%
Gamma delta T cells 1 0.02%
Macrophages 1 0.02%
Myeloid-derived suppressor cells 1 0.02%
Natural killer T cells 1 0.02%
Neural stem/precursor cells 1 0.02%
NK cells 1 0.02%
Trophoblast cells 1 0.02%
Unknown cell type 5728 97.51%

UMAPs

In this section, we show UMAPs colored by clusters. Clusters were calculated using the graph-based Louvain algorithm with Jaccard weighting.

Next, we show UMAPs colored by cell types. For each cell typing method, we show a separate faceted UMAP. In each panel, cells that were assigned the given cell type label are colored, while all other cells are in grey.

For legibility, only the seven most common cell types are shown. All other cell types are grouped together and labeled “All remaining cell types” (not to be confused with “Unknown cell type” which represents cells that could not be classified).

Session Info

R session information

## ─ Session info ───────────────────────────────────────────────────────────────
##  setting  value
##  version  R version 4.4.1 (2024-06-14)
##  os       Ubuntu 22.04.4 LTS
##  system   x86_64, linux-gnu
##  ui       X11
##  language (EN)
##  collate  en_US.UTF-8
##  ctype    en_US.UTF-8
##  tz       Etc/UTC
##  date     2024-08-02
##  pandoc   2.9.2.1 @ /usr/bin/ (via rmarkdown)
## 
## ─ Packages ───────────────────────────────────────────────────────────────────
##  package              * version  date (UTC) lib source
##  abind                  1.4-5    2016-07-21 [1] RSPM (R 4.4.0)
##  beachmat               2.20.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  beeswarm               0.4.0    2021-06-01 [1] RSPM (R 4.4.0)
##  Biobase              * 2.64.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  BiocGenerics         * 0.50.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  BiocNeighbors          1.22.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  BiocParallel           1.38.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  BiocSingular           1.20.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  bluster                1.14.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  bslib                  0.7.0    2024-03-29 [1] RSPM (R 4.4.0)
##  cachem                 1.1.0    2024-05-16 [1] RSPM (R 4.4.0)
##  cli                    3.6.3    2024-06-21 [1] RSPM (R 4.4.0)
##  cluster                2.1.6    2023-12-01 [2] CRAN (R 4.4.1)
##  codetools              0.2-20   2024-03-31 [2] CRAN (R 4.4.1)
##  colorspace             2.1-0    2023-01-23 [1] RSPM (R 4.4.0)
##  crayon                 1.5.3    2024-06-20 [1] RSPM (R 4.4.0)
##  DelayedArray           0.30.1   2024-05-07 [1] Bioconductor 3.19 (R 4.4.1)
##  DelayedMatrixStats     1.26.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  digest                 0.6.36   2024-06-23 [1] RSPM (R 4.4.0)
##  dplyr                * 1.1.4    2023-11-17 [1] RSPM (R 4.4.0)
##  dqrng                  0.4.1    2024-05-28 [1] RSPM (R 4.4.0)
##  edgeR                  4.2.0    2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  evaluate               0.24.0   2024-06-10 [1] RSPM (R 4.4.0)
##  fansi                  1.0.6    2023-12-08 [1] RSPM (R 4.4.0)
##  farver                 2.1.2    2024-05-13 [1] RSPM (R 4.4.0)
##  fastmap                1.2.0    2024-05-15 [1] RSPM (R 4.4.0)
##  flexmix                2.3-19   2023-03-16 [1] RSPM (R 4.4.0)
##  forcats                1.0.0    2023-01-29 [1] RSPM (R 4.4.0)
##  generics               0.1.3    2022-07-05 [1] RSPM (R 4.4.0)
##  GenomeInfoDb         * 1.40.1   2024-05-24 [1] Bioconductor 3.19 (R 4.4.1)
##  GenomeInfoDbData       1.2.12   2024-06-25 [1] Bioconductor
##  GenomicRanges        * 1.56.1   2024-06-12 [1] Bioconductor 3.19 (R 4.4.1)
##  getopt                 1.20.4   2023-10-01 [1] RSPM (R 4.4.0)
##  ggbeeswarm             0.7.2    2023-04-29 [1] RSPM (R 4.4.0)
##  ggplot2              * 3.5.1    2024-04-23 [1] RSPM (R 4.4.0)
##  ggrepel                0.9.5    2024-01-10 [1] RSPM (R 4.4.0)
##  glue                   1.7.0    2024-01-09 [1] RSPM (R 4.4.0)
##  gridExtra              2.3      2017-09-09 [1] RSPM (R 4.4.0)
##  gtable                 0.3.5    2024-04-22 [1] RSPM (R 4.4.0)
##  highr                  0.11     2024-05-26 [1] RSPM (R 4.4.0)
##  hms                    1.1.3    2023-03-21 [1] RSPM (R 4.4.0)
##  htmltools              0.5.8.1  2024-04-04 [1] RSPM (R 4.4.0)
##  httr                   1.4.7    2023-08-15 [1] RSPM (R 4.4.0)
##  igraph                 2.0.3    2024-03-13 [1] RSPM (R 4.4.0)
##  IRanges              * 2.38.1   2024-07-03 [1] Bioconductor 3.19 (R 4.4.1)
##  irlba                  2.3.5.1  2022-10-03 [1] RSPM (R 4.4.0)
##  jquerylib              0.1.4    2021-04-26 [1] RSPM (R 4.4.0)
##  jsonlite               1.8.8    2023-12-04 [1] RSPM (R 4.4.0)
##  kableExtra             1.4.0    2024-01-24 [1] RSPM (R 4.4.0)
##  knitr                  1.48     2024-07-07 [1] RSPM (R 4.4.0)
##  labeling               0.4.3    2023-08-29 [1] RSPM (R 4.4.0)
##  lattice                0.22-6   2024-03-20 [2] CRAN (R 4.4.1)
##  lifecycle              1.0.4    2023-11-07 [1] RSPM (R 4.4.0)
##  limma                  3.60.3   2024-06-16 [1] Bioconductor 3.19 (R 4.4.1)
##  locfit                 1.5-9.10 2024-06-24 [1] RSPM (R 4.4.0)
##  lubridate              1.9.3    2023-09-27 [1] RSPM (R 4.4.0)
##  magrittr               2.0.3    2022-03-30 [1] RSPM (R 4.4.0)
##  Matrix                 1.7-0    2024-04-26 [2] CRAN (R 4.4.1)
##  MatrixGenerics       * 1.16.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  matrixStats          * 1.3.0    2024-04-11 [1] RSPM (R 4.4.0)
##  metapod                1.12.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  miQC                   1.12.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  modeltools             0.2-23   2020-03-05 [1] RSPM (R 4.4.0)
##  munsell                0.5.1    2024-04-01 [1] RSPM (R 4.4.0)
##  nnet                   7.3-19   2023-05-03 [2] CRAN (R 4.4.1)
##  optparse             * 1.7.5    2024-04-16 [1] RSPM (R 4.4.0)
##  pillar                 1.9.0    2023-03-22 [1] RSPM (R 4.4.0)
##  pkgconfig              2.0.3    2019-09-22 [1] RSPM (R 4.4.0)
##  purrr                  1.0.2    2023-08-10 [1] RSPM (R 4.4.0)
##  R6                     2.5.1    2021-08-19 [1] RSPM (R 4.4.0)
##  RColorBrewer           1.1-3    2022-04-03 [1] RSPM (R 4.4.0)
##  Rcpp                   1.0.12   2024-01-09 [1] RSPM (R 4.4.0)
##  readr                  2.1.5    2024-01-10 [1] RSPM (R 4.4.0)
##  rlang                  1.1.4    2024-06-04 [1] RSPM (R 4.4.0)
##  rmarkdown              2.27     2024-05-17 [1] RSPM (R 4.4.0)
##  rstudioapi             0.16.0   2024-03-24 [1] RSPM (R 4.4.0)
##  rsvd                   1.0.5    2021-04-16 [1] RSPM (R 4.4.0)
##  S4Arrays               1.4.1    2024-05-20 [1] Bioconductor 3.19 (R 4.4.1)
##  S4Vectors            * 0.42.1   2024-07-03 [1] Bioconductor 3.19 (R 4.4.1)
##  sass                   0.4.9    2024-03-15 [1] RSPM (R 4.4.0)
##  ScaledMatrix           1.12.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  scales                 1.3.0    2023-11-28 [1] RSPM (R 4.4.0)
##  scater                 1.32.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  scpcaTools             0.4.0    2024-07-08 [1] local
##  scran                  1.32.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  scuttle                1.14.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  sessioninfo            1.2.2    2021-12-06 [1] RSPM (R 4.4.0)
##  SingleCellExperiment * 1.26.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  SparseArray            1.4.8    2024-05-24 [1] Bioconductor 3.19 (R 4.4.1)
##  sparseMatrixStats      1.16.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  statmod                1.5.0    2023-01-06 [1] RSPM (R 4.4.0)
##  stringi                1.8.4    2024-05-06 [1] RSPM (R 4.4.0)
##  stringr                1.5.1    2023-11-14 [1] RSPM (R 4.4.0)
##  SummarizedExperiment * 1.34.0   2024-05-01 [1] Bioconductor 3.19 (R 4.4.1)
##  svglite                2.1.3    2023-12-08 [1] RSPM (R 4.4.0)
##  systemfonts            1.1.0    2024-05-15 [1] RSPM (R 4.4.0)
##  tibble                 3.2.1    2023-03-20 [1] RSPM (R 4.4.0)
##  tidyr                  1.3.1    2024-01-24 [1] RSPM (R 4.4.0)
##  tidyselect             1.2.1    2024-03-11 [1] RSPM (R 4.4.0)
##  timechange             0.3.0    2024-01-18 [1] RSPM (R 4.4.0)
##  tzdb                   0.4.0    2023-05-12 [1] RSPM (R 4.4.0)
##  UCSC.utils             1.0.0    2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  utf8                   1.2.4    2023-10-22 [1] RSPM (R 4.4.0)
##  vctrs                  0.6.5    2023-12-01 [1] RSPM (R 4.4.0)
##  vipor                  0.4.7    2023-12-18 [1] RSPM (R 4.4.0)
##  viridis                0.6.5    2024-01-29 [1] RSPM (R 4.4.0)
##  viridisLite            0.4.2    2023-05-02 [1] RSPM (R 4.4.0)
##  withr                  3.0.0    2024-01-16 [1] RSPM (R 4.4.0)
##  xfun                   0.45     2024-06-16 [1] RSPM (R 4.4.0)
##  xml2                   1.3.6    2023-12-04 [1] RSPM (R 4.4.0)
##  XVector                0.44.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  yaml                   2.3.9    2024-07-05 [1] RSPM (R 4.4.0)
##  zlibbioc               1.50.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
## 
##  [1] /usr/local/lib/R/site-library
##  [2] /usr/local/lib/R/library
## 
## ──────────────────────────────────────────────────────────────────────────────
LS0tCnBhcmFtczoKICBsaWJyYXJ5OiBFeGFtcGxlCiAgdW5maWx0ZXJlZF9zY2U6ICFyIHNjcGNhVG9vbHM6OjpzaW1fc2NlKCkKICBmaWx0ZXJlZF9zY2U6IE5VTEwKICBwcm9jZXNzZWRfc2NlOiBOVUxMCiAgY2VsbHR5cGVfcmVwb3J0OiBOVUxMCiAgZGF0ZTogIXIgU3lzLkRhdGUoKQogIHNlZWQ6IE5VTEwKCnRpdGxlOiAiYHIgZ2x1ZTo6Z2x1ZSgnU2NQQ0EgUUMgcmVwb3J0IGZvciB7cGFyYW1zJGxpYnJhcnl9JylgIgphdXRob3I6ICJDaGlsZGhvb2QgQ2FuY2VyIERhdGEgTGFiIgpkYXRlOiAiYHIgcGFyYW1zJGRhdGVgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAyCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogZmFsc2UKICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgbWVzc2FnZSA9IEZBTFNFLCBlY2hvID0gRkFMU0V9CiMga25pdHIgb3B0aW9ucwprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZWNobyA9IEZBTFNFCikKCmxpYnJhcnkoU2luZ2xlQ2VsbEV4cGVyaW1lbnQpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgU2V0IGRlZmF1bHQgZ2dwbG90IHRoZW1lCnRoZW1lX3NldCgKICB0aGVtZV9idygpICsKICAgIHRoZW1lKAogICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbihyZXAoMjAsIDQpKSwKICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IikKICAgICkKKQoKIyBIZWxwZXIgZnVuY3Rpb24gdG8gY2hhbmdlIE5VTEwgLT4gIk4vQSIgaW4gYSBkYXRhIGZyYW1lCnJlZm9ybWF0X251bGxzIDwtIGZ1bmN0aW9uKGRmKSB7CiAgZGYgfD4gbXV0YXRlKAogICAgYWNyb3NzKGV2ZXJ5dGhpbmcoKSwKICAgICAgLmZucyA9IFwoeCkgaWZlbHNlKHggPT0gIk5VTEwiLCAiTi9BIiwgeCkKICAgICkKICApCn0KCiMgU2V0IHNlZWQKc2V0LnNlZWQocGFyYW1zJHNlZWQpCmBgYAoKCjwhLS0gc291cmNlIGZ1bmN0aW9ucyAtLT4gCmBgYHtyLCBjaGlsZD0ndXRpbHMvcmVwb3J0X2Z1bmN0aW9ucy5ybWQnfQpgYGAKCgpgYGB7ciBzY2Vfc2V0dXB9CiMgc2F2ZSBzb21lIHR5cGluZyBsYXRlcgpsaWJyYXJ5X2lkIDwtIHBhcmFtcyRsaWJyYXJ5CnVuZmlsdGVyZWRfc2NlIDwtIHBhcmFtcyR1bmZpbHRlcmVkX3NjZQpmaWx0ZXJlZF9zY2UgPC0gcGFyYW1zJGZpbHRlcmVkX3NjZQpwcm9jZXNzZWRfc2NlIDwtIHBhcmFtcyRwcm9jZXNzZWRfc2NlCgpoYXNfZmlsdGVyZWQgPC0gIWlzLm51bGwoZmlsdGVyZWRfc2NlKQpoYXNfcHJvY2Vzc2VkIDwtICFpcy5udWxsKHByb2Nlc3NlZF9zY2UpCgojIGlmIHRoZXJlIGlzIG5vIGZpbHRlcmVkIHNjZSwgdXNlIHRoZSB1bmZpbHRlcmVkIGZvciBib3RoCmlmICghaGFzX2ZpbHRlcmVkKSB7CiAgZmlsdGVyZWRfc2NlIDwtIHVuZmlsdGVyZWRfc2NlCn0KCiMgZ3JhYiBzYW1wbGUgaWQgZnJvbSBmaWx0ZXJlZCBzY2UsIGlmIG1pc3Npbmcgc2V0IHNhbXBsZSBpZCB0byBOQQppZiAoaXMubnVsbChtZXRhZGF0YShmaWx0ZXJlZF9zY2UpJHNhbXBsZV9pZCkpIHsKICBzYW1wbGVfaWQgPC0gTkEKfSBlbHNlIHsKICBzYW1wbGVfaWQgPC0gbWV0YWRhdGEoZmlsdGVyZWRfc2NlKSRzYW1wbGVfaWQKfQoKIyBhZGQgY2VsbCBzdGF0cyBpZiBtaXNzaW5nCmlmIChpcy5udWxsKHVuZmlsdGVyZWRfc2NlJHN1bSkpIHsKICB1bmZpbHRlcmVkX3NjZSA8LSBzY3V0dGxlOjphZGRQZXJDZWxsUUNNZXRyaWNzKHVuZmlsdGVyZWRfc2NlKQp9CmlmIChpcy5udWxsKGZpbHRlcmVkX3NjZSRzdW0pKSB7CiAgZmlsdGVyZWRfc2NlIDwtIHNjdXR0bGU6OmFkZFBlckNlbGxRQ01ldHJpY3MoZmlsdGVyZWRfc2NlKQp9CmlmIChpcy5udWxsKGZpbHRlcmVkX3NjZSRzdWJzZXRzX21pdG9fcGVyY2VudCkpIHsKICBmaWx0ZXJlZF9zY2Ukc3Vic2V0c19taXRvX3BlcmNlbnQgPC0gTkFfcmVhbF8KICBza2lwX21pUUMgPC0gVFJVRQp9IGVsc2UgewogIHNraXBfbWlRQyA8LSBGQUxTRQp9CgojIHRyeSB0byBhZGQgbWlRQyBpZiBpdCBpcyBtaXNzaW5nCmlmIChpcy5udWxsKG1ldGFkYXRhKGZpbHRlcmVkX3NjZSkkbWlRQ19tb2RlbCkgJiYgIXNraXBfbWlRQykgewogIGZpbHRlcmVkX3NjZSA8LSBzY3BjYVRvb2xzOjphZGRfbWlRQyhmaWx0ZXJlZF9zY2UpCn0KCiMjIENoZWNrIGZvciBhZGRpdGlvbmFsIG1vZGFsaXRpZXMKbW9kYWxpdGllcyA8LSBjKCJSTkEtc2VxIikKCmhhc19hZHQgPC0gImFkdCIgJWluJSBhbHRFeHBOYW1lcyhmaWx0ZXJlZF9zY2UpCmlmIChoYXNfYWR0KSB7CiAgbW9kYWxpdGllcyA8LSBjKG1vZGFsaXRpZXMsICJBRFQiKQp9CgojIGNoZWNrIGZvciBjZWxsaGFzaCB0byBhZGQgdG8gbGlzdCBvZiBtb2RhbGl0aWVzCmhhc19jZWxsaGFzaCA8LSAiY2VsbGhhc2giICVpbiUgYWx0RXhwTmFtZXMoZmlsdGVyZWRfc2NlKQppZiAoaGFzX2NlbGxoYXNoKSB7CiAgbW9kYWxpdGllcyA8LSBjKG1vZGFsaXRpZXMsICJNdWx0aXBsZXgiKQp9CgojIGNoZWNrIGZvciB1bWFwIGFuZCBjZWxsdHlwZXMsIGJ1dCBuZWVkIHRvIGJlIHN1cmUgdGhhdCBwcm9jZXNzZWRfc2NlIGV4aXN0cyBmaXJzdAppZiAoaGFzX3Byb2Nlc3NlZCkgewogIGhhc191bWFwIDwtICJVTUFQIiAlaW4lIHJlZHVjZWREaW1OYW1lcyhwcm9jZXNzZWRfc2NlKQogIGhhc19jbHVzdGVycyA8LSAiY2x1c3RlciIgJWluJSBuYW1lcyhjb2xEYXRhKHByb2Nlc3NlZF9zY2UpKQogIGhhc19zaW5nbGVyIDwtICJzaW5nbGVyIiAlaW4lIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJGNlbGx0eXBlX21ldGhvZHMKICBoYXNfY2VsbGFzc2lnbiA8LSAiY2VsbGFzc2lnbiIgJWluJSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRjZWxsdHlwZV9tZXRob2RzCiAgaGFzX3N1Ym1pdHRlciA8LSAic3VibWl0dGVyIiAlaW4lIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJGNlbGx0eXBlX21ldGhvZHMgJiYKICAgICFhbGwoaXMubmEocHJvY2Vzc2VkX3NjZSRzdWJtaXR0ZXJfY2VsbHR5cGVfYW5ub3RhdGlvbikpICMgbWFrZSBzdXJlIHRoZXkgYXJlbid0IGFsbCBOQQoKICAjIElmIGF0IGxlYXN0IDEgaXMgcHJlc2VudCwgd2UgaGF2ZSBjZWxsIHR5cGUgYW5ub3RhdGlvbnMuCiAgaGFzX2NlbGx0eXBlcyA8LSBhbnkoaGFzX3NpbmdsZXIsIGhhc19jZWxsYXNzaWduLCBoYXNfc3VibWl0dGVyKQoKICBpc19zdXBwbGVtZW50YWwgPC0gRkFMU0UgIyB0aGlzIGlzIG5vdCB0aGUgY2VsbHR5cGUgc3VwcCByZXBvcnQKfSBlbHNlIHsKICBoYXNfdW1hcCA8LSBGQUxTRQogIGhhc19jbHVzdGVycyA8LSBGQUxTRQogIGhhc19zaW5nbGVyIDwtIEZBTFNFCiAgaGFzX2NlbGxhc3NpZ24gPC0gRkFMU0UKICBoYXNfc3VibWl0dGVyIDwtIEZBTFNFCiAgaGFzX2NlbGx0eXBlcyA8LSBGQUxTRQp9CgojIGNoZWNrIGZvciBjZWxsdHlwZXNfcmVwb3J0IGlmIGNlbGx0eXBlcyBhcmUgcHJlc2VudAppZiAoKGhhc19zaW5nbGVyIHwgaGFzX2NlbGxhc3NpZ24pICYgaXMubnVsbChwYXJhbXMkY2VsbHR5cGVfcmVwb3J0KSkgewogIHN0b3AoIkNlbGwgdHlwZSBhbm5vdGF0aW9ucyB3ZXJlIHByb3ZpZGVkIGJ1dCB0aGUgcGFyYW1ldGVyIHNwZWNpZnlpbmcgdGhlIGNlbGwgdHlwZSByZXBvcnQgZmlsZSBpcyBtaXNzaW5nLiIpCn0KCiMgY2hlY2sgaWYgd2UgaGF2ZSBtdWx0aXBsZXgKaGFzX211bHRpcGxleCA8LSBsZW5ndGgoc2FtcGxlX2lkKSA+IDEKc2FtcGxlX3R5cGVzIDwtIG1ldGFkYXRhKHVuZmlsdGVyZWRfc2NlKSRzYW1wbGVfdHlwZQpgYGAKCgpgYGB7ciwgcmVzdWx0cz0nYXNpcyd9CiMgb25seSBwcmludCBvdXQgaW5mbyBib3ggaWYgeGVub2dyYWZ0IG9yIGNlbGwgbGluZSwgd2l0aCBkaWZmZXJlbnQgbG9naWMvd2FybmluZ3MKIyBmb3IgbXVsdGlwbGV4IGxpYnJhcmllcwppZiAoInBhdGllbnQtZGVyaXZlZCB4ZW5vZ3JhZnQiICVpbiUgc2FtcGxlX3R5cGVzKSB7CiAgIyBkZXRlcm1pbmUgd2hpY2ggc2FtcGxlcyBhcmUgdGhlIFBEWHMKICBpZiAoaGFzX211bHRpcGxleCkgewogICAgIyBnZXQgYSBsaXN0IG9mIHNhbXBsZXMgaW4gdGhlIGxpYnJhcnkgdGhhdCBhcmUgcGR4cwogICAgcGR4X3NhbXBsZXMgPC0gbmFtZXMoc2FtcGxlX3R5cGVzW3NhbXBsZV90eXBlcyA9PSAicGF0aWVudC1kZXJpdmVkIHhlbm9ncmFmdCJdKQogICAgcGR4X3NhbXBsZXNfYnVsbGV0cyA8LSBwYXN0ZTAoIjxsaT4iLCBwYXN0ZShwZHhfc2FtcGxlcywgY29sbGFwc2UgPSAiPC9saT48bGk+IiwgIjwvbGk+IikpCgogICAgZ2x1ZTo6Z2x1ZSgiCiAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1pbmZvXCI+CgogICAgICBUaGlzIGxpYnJhcnkgaW5jbHVkZXMgcGF0aWVudC1kZXJpdmVkIHhlbm9ncmFmdCBzYW1wbGVzLgogICAgICBUaGUgZm9sbG93aW5nIHNhbXBsZXMgYXJlIGRlcml2ZWQgZnJvbSBwYXRpZW50IHhlbm9ncmFmdHM6CgogICAgICB7cGR4X3NhbXBsZXNfYnVsbGV0c30KCiAgICAgIDwvZGl2PgogICAgIikKICB9IGVsc2UgewogICAgZ2x1ZTo6Z2x1ZSgiCiAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1pbmZvXCI+CgogICAgICBUaGlzIGxpYnJhcnkgY29tZXMgZnJvbSBhIHBhdGllbnQtZGVyaXZlZCB4ZW5vZ3JhZnQgc2FtcGxlLgoKICAgICAgPC9kaXY+CiAgICAiKQogIH0KfQoKaWYgKCJjZWxsIGxpbmUiICVpbiUgc2FtcGxlX3R5cGVzKSB7CiAgaWYgKGhhc19tdWx0aXBsZXgpIHsKICAgICMgZ2V0IGEgbGlzdCBvZiBzYW1wbGVzIGluIHRoZSBsaWJyYXJ5IHRoYXQgYXJlIGNlbGwgbGluZXMKICAgIGNlbGxfbGluZV9zYW1wbGVzIDwtIG5hbWVzKHNhbXBsZV90eXBlc1tzYW1wbGVfdHlwZXMgPT0gImNlbGwgbGluZSJdKQogICAgY2VsbF9saW5lX3NhbXBsZXNfYnVsbGV0cyA8LSBwYXN0ZTAoIjxsaT4iLCBwYXN0ZShjZWxsX2xpbmVfc2FtcGxlcywgY29sbGFwc2UgPSAiPC9saT48bGk+IiwgIjwvbGk+IikpCgogICAgZ2x1ZTo6Z2x1ZSgiCiAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1pbmZvXCI+CgogICAgICBUaGlzIGxpYnJhcnkgaW5jbHVkZXMgY2VsbCBsaW5lIHNhbXBsZXMuCiAgICAgIFBsZWFzZSBiZSBhd2FyZSB0aGF0IG5vIGNlbGwgdHlwZSBhbm5vdGF0aW9uIGlzIHBlcmZvcm1lZCBmb3IgY2VsbCBsaW5lIHNhbXBsZXMuCiAgICAgIFRoZSBmb2xsb3dpbmcgc2FtcGxlcyBhcmUgZGVyaXZlZCBmcm9tIGNlbGwgbGluZXM6CgogICAgICB7Y2VsbF9saW5lX3NhbXBsZXNfYnVsbGV0c30KCiAgICAgIDwvZGl2PgogICAgIikKICB9IGVsc2UgewogICAgZ2x1ZTo6Z2x1ZSgiCiAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1pbmZvXCI+CgogICAgICBUaGlzIGxpYnJhcnkgY29tZXMgZnJvbSBhIGNlbGwgbGluZSBzYW1wbGUuCiAgICAgIFBsZWFzZSBiZSBhd2FyZSB0aGF0IG5vIGNlbGwgdHlwZSBhbm5vdGF0aW9uIGlzIHBlcmZvcm1lZCBmb3IgY2VsbCBsaW5lIHNhbXBsZXMuCgogICAgICA8L2Rpdj4KICAgICIpCiAgfQp9CmBgYAoKIyBNZXRhZGF0YSBhbmQgUHJvY2Vzc2luZyBJbmZvcm1hdGlvbiBmb3IgYHIgbGlicmFyeV9pZGAKCmBgYHtyLCBldmFsID0gaGFzX211bHRpcGxleCwgcmVzdWx0cz0nYXNpcyd9CiMgY29udmVydCBzYW1wbGUgaWQgdG8gYnVsbGV0IHNlcGFyYXRlZCBsaXN0Cm11bHRpcGxleF9zYW1wbGVzIDwtIHBhc3RlMCgiPGxpPiIsIHBhc3RlKHNhbXBsZV9pZCwgY29sbGFwc2UgPSAiPC9saT48bGk+IiwgIjwvbGk+IikpCmdsdWU6OmdsdWUoIgogIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC13YXJuaW5nXCI+CgogIFRoaXMgbGlicmFyeSBpcyBtdWx0aXBsZXhlZCBhbmQgY29udGFpbnMgZGF0YSBmcm9tIG1vcmUgdGhhbiBvbmUgc2FtcGxlLgogIERhdGEgZnJvbSB0aGUgZm9sbG93aW5nIHNhbXBsZXMgYXJlIGluY2x1ZGVkIGluIHRoaXMgbGlicmFyeToKCiAge211bHRpcGxleF9zYW1wbGVzfQoKICA8L2Rpdj4KIikKYGBgCgojIyBTYW1wbGUgTWV0YWRhdGEKClRoZSBiZWxvdyB0YWJsZSBzdW1tYXJpemVzIGNsaW5pY2FsIG1ldGFkYXRhIGZvciB0aGUgc2FtcGxlIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGxpYnJhcnkuIApCbHVlIGh5cGVybGlua3MgYXJlIHByZXNlbnQgZm9yIGFueSB0ZXJtcyB3aXRoIGFuIG9udG9sb2d5IHRlcm0gaWRlbnRpZmllciBhc3NvY2lhdGVkIHdpdGggdGhlIGRpc3BsYXllZCBodW1hbiByZWFkYWJsZSB2YWx1ZS4gClRoZXNlIGxpbmtzIHdpbGwgZGlyZWN0IHlvdSB0byBhIHdlYiBwYWdlIHdpdGggaW5mb3JtYXRpb24gYWJvdXQgdGhhdCBvbnRvbG9neSB0ZXJtIGlkZW50aWZpZXIuICAKCmBgYHtyfQojIGV4dHJhY3Qgc2NlIG1ldGFkYXRhIGNvbnRhaW5pbmcgcHJvY2Vzc2luZyBpbmZvcm1hdGlvbiBhcyB0YWJsZQp1bmZpbHRlcmVkX21ldGEgPC0gbWV0YWRhdGEodW5maWx0ZXJlZF9zY2UpCgojIGlmIGRhdGEgaXMgbm90IG11bHRpcGxleGVkLCBwcmludCBvdXQgc2FtcGxlIG1ldGFkYXRhCmlmICghaGFzX211bHRpcGxleCkgewogIHByaW50X3NhbXBsZV9tZXRhZGF0YSh1bmZpbHRlcmVkX21ldGEpCn0gZWxzZSB7CiAgIyBvdGhlcndpc2UgcHJpbnQgb3V0IGFuIGluZm8gYm94IHRoYXQgbm8gc2FtcGxlIG1ldGFkYXRhIHdpbGwgYmUgZGlzcGxheWVkCiAga25pdHI6OmFzaXNfb3V0cHV0KAogICAgZ2x1ZTo6Z2x1ZSgiCiAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1pbmZvXCI+CgogICAgICBUaGlzIGxpYnJhcnkgaXMgbXVsdGlwbGV4ZWQgYW5kIGNvbnRhaW5zIGRhdGEgZnJvbSBtb3JlIHRoYW4gb25lIHNhbXBsZS4KICAgICAgRGVtdWx0aXBsZXhpbmcgaGFzIG5vdCBiZWVuIHBlcmZvcm1lZCwgc28gc2FtcGxlIG1ldGFkYXRhIHdpbGwgbm90IGJlIGRpc3BsYXllZC4KICAgICAgPC9kaXY+CiAgICAiKQogICkKfQpgYGAKCiMjIFJhdyBMaWJyYXJ5IE1ldHJpY3MKCmBgYHtyIH0KIyBleHRyYWN0IHNjZSBtZXRhZGF0YSBjb250YWluaW5nIHByb2Nlc3NpbmcgaW5mb3JtYXRpb24gYXMgdGFibGUKdW5maWx0ZXJlZF9tZXRhIDwtIG1ldGFkYXRhKHVuZmlsdGVyZWRfc2NlKQoKbGlicmFyeV9pbmZvcm1hdGlvbiA8LSB0aWJibGU6OnRpYmJsZSgKICAiTGlicmFyeSBpZCIgPSBsaWJyYXJ5X2lkLAogICJTYW1wbGUgaWQiID0gcGFzdGUoc2FtcGxlX2lkLCBjb2xsYXBzZSA9ICIsICIpLAogICJUZWNoIHZlcnNpb24iID0gZm9ybWF0KHVuZmlsdGVyZWRfbWV0YSR0ZWNoX3ZlcnNpb24pLCAjIGZvcm1hdCB0byBrZWVwIG51bGxzCiAgIkRhdGEgbW9kYWxpdGllcyIgPSBwYXN0ZShtb2RhbGl0aWVzLCBjb2xsYXBzZSA9ICIsICIpLAogICJDZWxscyByZXBvcnRlZCBieSBhbGV2aW4tZnJ5IiA9CiAgICBmb3JtYXQodW5maWx0ZXJlZF9tZXRhJGFmX251bV9jZWxscywgYmlnLm1hcmsgPSAiLCIsIHNjaWVudGlmaWMgPSBGQUxTRSksCiAgIk51bWJlciBvZiBnZW5lcyBhc3NheWVkIiA9CiAgICBmb3JtYXQobnJvdyh1bmZpbHRlcmVkX3NjZSksIGJpZy5tYXJrID0gIiwiLCBzY2llbnRpZmljID0gRkFMU0UpLAogICJOdW1iZXIgb2YgUk5BLXNlcSByZWFkcyBzZXF1ZW5jZWQiID0KICAgIGZvcm1hdCh1bmZpbHRlcmVkX21ldGEkdG90YWxfcmVhZHMsIGJpZy5tYXJrID0gIiwiLCBzY2llbnRpZmljID0gRkFMU0UpLAogICJQZXJjZW50IG9mIFJOQS1zZXEgcmVhZHMgbWFwcGVkIHRvIHRyYW5zY3JpcHRzIiA9CiAgICBwYXN0ZTAocm91bmQoKHVuZmlsdGVyZWRfbWV0YSRtYXBwZWRfcmVhZHMgLyB1bmZpbHRlcmVkX21ldGEkdG90YWxfcmVhZHMpICogMTAwLCAyKSwgIiUiKQopCgppZiAoaGFzX2FkdCkgewogIGFkdF9leHAgPC0gYWx0RXhwKGZpbHRlcmVkX3NjZSwgImFkdCIpICMgbXVzdCBiZSBmaWx0ZXJlZF9zY2UgaW4gY2FzZSBoYXNfcHJvY2Vzc2VkIGlzIEZBTFNFCiAgYWR0X21ldGEgPC0gbWV0YWRhdGEoYWR0X2V4cCkKCiAgbGlicmFyeV9pbmZvcm1hdGlvbiA8LSBsaWJyYXJ5X2luZm9ybWF0aW9uIHw+CiAgICBtdXRhdGUoCiAgICAgICJOdW1iZXIgb2YgYW50aWJvZGllcyBhc3NheWVkIiA9CiAgICAgICAgZm9ybWF0KG5yb3coYWR0X2V4cCksIGJpZy5tYXJrID0gIiwiLCBzY2llbnRpZmljID0gRkFMU0UpLAogICAgICAiTnVtYmVyIG9mIEFEVCByZWFkcyBzZXF1ZW5jZWQiID0KICAgICAgICBmb3JtYXQoYWR0X21ldGEkdG90YWxfcmVhZHMsIGJpZy5tYXJrID0gIiwiLCBzY2llbnRpZmljID0gRkFMU0UpLAogICAgICAiUGVyY2VudCBvZiBBRFQgcmVhZHMgbWFwcGVkIHRvIEFEVHMiID0KICAgICAgICBwYXN0ZTAocm91bmQoYWR0X21ldGEkbWFwcGVkX3JlYWRzIC8gYWR0X21ldGEkdG90YWxfcmVhZHMgKiAxMDAsIGRpZ2l0cyA9IDIpLCAiJSIpCiAgICApCn0KCmlmIChoYXNfY2VsbGhhc2gpIHsKICBtdWx0aXBsZXhfZXhwIDwtIGFsdEV4cChmaWx0ZXJlZF9zY2UsICJjZWxsaGFzaCIpCiAgbXVsdGlwbGV4X21ldGEgPC0gbWV0YWRhdGEobXVsdGlwbGV4X2V4cCkKCiAgbGlicmFyeV9pbmZvcm1hdGlvbiA8LSBsaWJyYXJ5X2luZm9ybWF0aW9uIHw+CiAgICBtdXRhdGUoCiAgICAgICJOdW1iZXIgb2YgSFRPcyBhc3NheWVkIiA9CiAgICAgICAgZm9ybWF0KG5yb3cobXVsdGlwbGV4X2V4cCksIGJpZy5tYXJrID0gIiwiLCBzY2llbnRpZmljID0gRkFMU0UpLAogICAgICAiTnVtYmVyIG9mIGNlbGxoYXNoIHJlYWRzIHNlcXVlbmNlZCIgPQogICAgICAgIGZvcm1hdChtdWx0aXBsZXhfbWV0YSR0b3RhbF9yZWFkcywgYmlnLm1hcmsgPSAiLCIsIHNjaWVudGlmaWMgPSBGQUxTRSksCiAgICAgICJQZXJjZW50IG9mIGNlbGxoYXNoIHJlYWRzIG1hcHBlZCB0byBIVE9zIiA9CiAgICAgICAgcGFzdGUwKHJvdW5kKG11bHRpcGxleF9tZXRhJG1hcHBlZF9yZWFkcyAvIG11bHRpcGxleF9tZXRhJHRvdGFsX3JlYWRzICogMTAwLCBkaWdpdHMgPSAyKSwgIiUiKQogICAgKQp9CgpsaWJyYXJ5X2luZm9ybWF0aW9uIDwtIGxpYnJhcnlfaW5mb3JtYXRpb24gfD4KICByZWZvcm1hdF9udWxscygpIHw+CiAgdCgpCgojIG1ha2UgdGFibGUgd2l0aCBzYW1wbGUgaW5mb3JtYXRpb24Ka25pdHI6OmthYmxlKGxpYnJhcnlfaW5mb3JtYXRpb24sIGFsaWduID0gInIiKSB8PgogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoCiAgICBib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwKICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwKICAgIHBvc2l0aW9uID0gImxlZnQiCiAgKSB8PgogIGthYmxlRXh0cmE6OmNvbHVtbl9zcGVjKDIsIG1vbm9zcGFjZSA9IFRSVUUpCmBgYAoKIyMgUHJlLVByb2Nlc3NpbmcgSW5mb3JtYXRpb24KCmBgYHtyIH0KIyBkZWZpbmUgdHJhbnNjcmlwdCB0eXBlCnRyYW5zY3JpcHRfdHlwZSA8LSBwYXN0ZSh1bmZpbHRlcmVkX21ldGEkdHJhbnNjcmlwdF90eXBlLCBjb2xsYXBzZSA9ICIgIikKCnByb2Nlc3NpbmdfaW5mbyA8LSB0aWJibGU6OnRpYmJsZSgKICAiU2FsbW9uIHZlcnNpb24iID0gZm9ybWF0KHVuZmlsdGVyZWRfbWV0YSRzYWxtb25fdmVyc2lvbiksCiAgIkFsZXZpbi1mcnkgdmVyc2lvbiIgPSBmb3JtYXQodW5maWx0ZXJlZF9tZXRhJGFsZXZpbmZyeV92ZXJzaW9uKSwKICAiVHJhbnNjcmlwdG9tZSBpbmRleCIgPSBmb3JtYXQodW5maWx0ZXJlZF9tZXRhJHJlZmVyZW5jZV9pbmRleCksCiAgIkFsZXZpbi1mcnkgZHJvcGxldCBkZXRlY3Rpb24iID0gZm9ybWF0KHVuZmlsdGVyZWRfbWV0YSRhZl9wZXJtaXRfdHlwZSksCiAgIlJlc29sdXRpb24iID0gZm9ybWF0KHVuZmlsdGVyZWRfbWV0YSRhZl9yZXNvbHV0aW9uKSwKICAiVHJhbnNjcmlwdHMgaW5jbHVkZWQiID0gZHBseXI6OmNhc2Vfd2hlbigKICAgIHRyYW5zY3JpcHRfdHlwZSA9PSAidG90YWwgc3BsaWNlZCIgfiAiVG90YWwgYW5kIHNwbGljZWQgb25seSIsCiAgICB0cmFuc2NyaXB0X3R5cGUgPT0gInNwbGljZWQiIH4gIlNwbGljZWQgb25seSIsCiAgICBUUlVFIH4gdHJhbnNjcmlwdF90eXBlCiAgKQopIHw+CiAgcmVmb3JtYXRfbnVsbHMoKSB8PgogIHQoKQoKCiMgbWFrZSB0YWJsZSB3aXRoIHByb2Nlc3NpbmcgaW5mb3JtYXRpb24Ka25pdHI6OmthYmxlKHByb2Nlc3NpbmdfaW5mbywgYWxpZ24gPSAiciIpIHw+CiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZygKICAgIGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLAogICAgZnVsbF93aWR0aCA9IEZBTFNFLAogICAgcG9zaXRpb24gPSAibGVmdCIKICApIHw+CiAga2FibGVFeHRyYTo6Y29sdW1uX3NwZWMoMiwgbW9ub3NwYWNlID0gVFJVRSkKYGBgCgojIFJOQS1zZXEgRXhwZXJpbWVudCBTdW1tYXJ5CgojIyBDZWxsIFN0YXRpc3RpY3MKCmBgYHtyfQpiYXNpY19zdGF0aXN0aWNzIDwtIHRpYmJsZTo6dGliYmxlKAogICJNZXRob2QgdXNlZCB0byBmaWx0ZXIgZW1wdHkgZHJvcGxldHMiICAgICAgICAgID0gbWV0YWRhdGEoZmlsdGVyZWRfc2NlKSRmaWx0ZXJpbmdfbWV0aG9kLAogICJOdW1iZXIgb2YgY2VsbHMgcG9zdCBmaWx0ZXJpbmcgZW1wdHkgZHJvcGxldHMiID0gZm9ybWF0KG5jb2woZmlsdGVyZWRfc2NlKSwgYmlnLm1hcmsgPSAiLCIpLAogICJQZXJjZW50IG9mIHJlYWRzIGluIGNlbGxzIiAgICAgICAgICAgICAgICAgICAgID0gcGFzdGUwKHJvdW5kKChzdW0oZmlsdGVyZWRfc2NlJHN1bSkgLyBzdW0odW5maWx0ZXJlZF9zY2Ukc3VtKSkgKiAxMDAsIDIpLCAiJSIpLAogICJNZWRpYW4gVU1JIGNvdW50IHBlciBjZWxsIiAgICAgICAgICAgICAgICAgICAgID0gZm9ybWF0KG1lZGlhbihmaWx0ZXJlZF9zY2Ukc3VtKSwgYmlnLm1hcmsgPSAiLCIpLAogICJNZWRpYW4gZ2VuZXMgZGV0ZWN0ZWQgcGVyIGNlbGwiICAgICAgICAgICAgICAgID0gZm9ybWF0KG1lZGlhbihmaWx0ZXJlZF9zY2UkZGV0ZWN0ZWQpLCBiaWcubWFyayA9ICIsIiksCiAgIk1lZGlhbiBwZXJjZW50IHJlYWRzIG1pdG9jaG9uZHJpYWwiICAgICAgICAgICAgPSBwYXN0ZTAocm91bmQobWVkaWFuKGZpbHRlcmVkX3NjZSRzdWJzZXRzX21pdG9fcGVyY2VudCksIDIpLCAiJSIpCikKCiMgaWYgcHJvY2Vzc2VkIHNjZSBleGlzdHMgYWRkIGZpbHRlcmluZyBhbmQgbm9ybWFsaXphdGlvbiB0YWJsZQppZiAoaGFzX3Byb2Nlc3NlZCkgewogIHByb2Nlc3NlZF9tZXRhIDwtIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpCgogIGJhc2ljX3N0YXRpc3RpY3MgPC0gYmFzaWNfc3RhdGlzdGljcyB8PgogICAgbXV0YXRlKAogICAgICAiTWV0aG9kIHVzZWQgdG8gZmlsdGVyIGxvdyBxdWFsaXR5IGNlbGxzIiA9IGZvcm1hdChwcm9jZXNzZWRfbWV0YSRzY3BjYV9maWx0ZXJfbWV0aG9kKSwKICAgICAgIkNlbGxzIGFmdGVyIGZpbHRlcmluZyBsb3cgcXVhbGl0eSBjZWxscyIgPSBmb3JtYXQoZGltKHByb2Nlc3NlZF9zY2UpWzJdLCBiaWcubWFyayA9ICIsIiwgc2NpZW50aWZpYyA9IEZBTFNFKSwKICAgICAgIk5vcm1hbGl6YXRpb24gbWV0aG9kIiAgICAgICAgICAgICAgICAgICAgPSBmb3JtYXQocHJvY2Vzc2VkX21ldGEkbm9ybWFsaXphdGlvbiksCiAgICAgICJNaW5pbXVtIGdlbmVzIHBlciBjZWxsIGN1dG9mZiIgICAgICAgICAgID0gZm9ybWF0KHByb2Nlc3NlZF9tZXRhJG1pbl9nZW5lX2N1dG9mZikKICAgICkKICBpZiAocHJvY2Vzc2VkX21ldGEkc2NwY2FfZmlsdGVyX21ldGhvZCA9PSAibWlRQyIpIHsKICAgIGJhc2ljX3N0YXRpc3RpY3MgPC0gYmFzaWNfc3RhdGlzdGljcyB8PgogICAgICBtdXRhdGUoCiAgICAgICAgIlByb2JhYmlsaXR5IG9mIGNvbXByb21pc2VkIGNlbGwgY3V0b2ZmIiA9IGZvcm1hdChwcm9jZXNzZWRfbWV0YSRwcm9iX2NvbXByb21pc2VkX2N1dG9mZiwgYmlnLm1hcmsgPSAiLCIsIHNjaWVudGlmaWMgPSBGQUxTRSkKICAgICAgKQogIH0KfQoKYmFzaWNfc3RhdGlzdGljcyA8LSBiYXNpY19zdGF0aXN0aWNzIHw+CiAgcmVmb3JtYXRfbnVsbHMoKSB8PiAjIHJlZm9ybWF0IG51bGxzCiAgdCgpCgojIG1ha2UgdGFibGUgd2l0aCBiYXNpYyBzdGF0aXN0aWNzCmtuaXRyOjprYWJsZShiYXNpY19zdGF0aXN0aWNzLCBhbGlnbiA9ICJyIikgfD4KICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKAogICAgYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsCiAgICBmdWxsX3dpZHRoID0gRkFMU0UsCiAgICBwb3NpdGlvbiA9ICJsZWZ0IgogICkgfD4KICBrYWJsZUV4dHJhOjpjb2x1bW5fc3BlYygyLCBtb25vc3BhY2UgPSBUUlVFKQpgYGAKCmBgYHtyLCByZXN1bHRzPSdhc2lzJ30KaWYgKAogIGhhc19maWx0ZXJlZCAmJgogICAgKG1ldGFkYXRhKGZpbHRlcmVkX3NjZSkkZmlsdGVyaW5nX21ldGhvZCA9PSAiVU1JIGN1dG9mZiIpCikgewogIGdsdWU6OmdsdWUoIgogICAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXdhcm5pbmdcIj4KCiAgICBUaGlzIGxpYnJhcnkgbWF5IGNvbnRhaW4gYSBsb3cgbnVtYmVyIG9mIGNlbGxzIGFuZCB3YXMgdW5hYmxlIHRvIGJlIGZpbHRlcmVkIHVzaW5nIGBEcm9wbGV0VXRpbHNgLgogICAgRHJvcGxldHMgd2l0aCBhIHRvdGFsIFVNSSBjb3VudCDiiaUge21ldGFkYXRhKGZpbHRlcmVkX3NjZSkkdW1pX2N1dG9mZn0gYXJlIGluY2x1ZGVkIGluIHRoZSBmaWx0ZXJlZCBgU2luZ2xlQ2VsbEV4cGVyaW1lbnRgIG9iamVjdC4KCiAgICA8L2Rpdj4KICAiKQp9CmBgYAoKYGBge3IsIHJlc3VsdHM9J2FzaXMnfQojIGNoZWNrIGZvciBudW1iZXIgb2YgZmlsdGVyZWQgY2VsbHMKbWluX2ZpbHRlcmVkIDwtIDEwMAppZiAoaGFzX2ZpbHRlcmVkKSB7CiAgaWYgKG5jb2woZmlsdGVyZWRfc2NlKSA8IG1pbl9maWx0ZXJlZCkgewogICAgZ2x1ZTo6Z2x1ZSgiCiAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC13YXJuaW5nXCI+CgogICAgICBUaGlzIGxpYnJhcnkgY29udGFpbnMgZmV3ZXIgdGhhbiB7bWluX2ZpbHRlcmVkfSBjZWxscyBpbiB0aGUgZmlsdGVyZWQgYFNpbmdsZUNlbGxFeHBlcmltZW50YCBvYmplY3QuCiAgICAgIFRoaXMgbWF5IGFmZmVjdCB0aGUgaW50ZXJwcmV0YXRpb24gb2YgcmVzdWx0cy4KCiAgICAgIDwvZGl2PgogICAgIikKICB9Cn0KCiMgY2hlY2sgZm9yIG51bWJlciBvZiBjZWxscyBwb3N0IHByb2Nlc3NpbmcKbWluX3Byb2Nlc3NlZCA8LSA1MAppZiAoaGFzX3Byb2Nlc3NlZCkgewogIGlmIChuY29sKHByb2Nlc3NlZF9zY2UpIDwgbWluX3Byb2Nlc3NlZCkgewogICAgZ2x1ZTo6Z2x1ZSgiCiAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC13YXJuaW5nXCI+CgogICAgICBUaGlzIGxpYnJhcnkgY29udGFpbnMgZmV3ZXIgdGhhbiB7bWluX3Byb2Nlc3NlZH0gY2VsbHMgaW4gdGhlIHByb2Nlc3NlZCBgU2luZ2xlQ2VsbEV4cGVyaW1lbnRgIG9iamVjdCBhZnRlciByZW1vdmFsIG9mIGxvdyBxdWFsaXR5IGNlbGxzLgogICAgICBVTUFQIGlzIHVuYWJsZSB0byBiZSBjYWxjdWxhdGVkIGFuZCBwbG90cyB3aWxsIG5vdCBiZSBzaG93bi4KCiAgICAgIDwvZGl2PgogICAgIikKICB9Cn0KYGBgCgojIyBLbmVlIFBsb3QKCmBgYHtyLCBmaWcuYWx0PSJTbW9vdGhlZCBrbmVlIHBsb3Qgb2YgZmlsdGVyZWQgYW5kIHVuZmlsdGVyZWQgZHJvcGxldHMifQp1bmZpbHRlcmVkX2NlbGxkYXRhIDwtIGRhdGEuZnJhbWUoY29sRGF0YSh1bmZpbHRlcmVkX3NjZSkpIHw+CiAgbXV0YXRlKAogICAgcmFuayA9IHJhbmsoLXVuZmlsdGVyZWRfc2NlJHN1bSwgdGllcy5tZXRob2QgPSAiZmlyc3QiKSwgIyB1c2luZyBmdWxsIHNwZWMgZm9yIGNsYXJpdHkKICAgIGZpbHRlcl9wYXNzID0gY29sbmFtZXModW5maWx0ZXJlZF9zY2UpICVpbiUgY29sbmFtZXMoZmlsdGVyZWRfc2NlKQogICkgfD4KICBzZWxlY3Qoc3VtLCByYW5rLCBmaWx0ZXJfcGFzcykgfD4KICBmaWx0ZXIoc3VtID4gMCkgIyByZW1vdmUgemVyb3MgZm9yIHBsb3R0aW5nCgoKZ3JvdXBlZF9jZWxsZGF0YSA8LSB1bmZpbHRlcmVkX2NlbGxkYXRhIHw+CiAgbXV0YXRlKHJhbmtfZ3JvdXAgPSBmbG9vcihyYW5rIC8gMTAwKSkgfD4KICBncm91cF9ieShyYW5rX2dyb3VwKSB8PgogIHN1bW1hcml6ZSgKICAgIG1lZF9zdW0gPSBtZWRpYW4oc3VtKSwKICAgIG1lZF9yYW5rID0gbWVkaWFuKHJhbmspLAogICAgcGN0X3Bhc3NlZCA9IHN1bShmaWx0ZXJfcGFzcykgLyBuKCkgKiAxMDAKICApCgp0b3BfY2VsbGRhdGEgPC0gdW5maWx0ZXJlZF9jZWxsZGF0YSB8PgogIGZpbHRlcihyYW5rIDw9IDUwKSB8PgogIG11dGF0ZShmaWx0ZXJfcGN0ID0gaWZlbHNlKGZpbHRlcl9wYXNzLCAxMDAsIDApKQoKZ2dwbG90KGdyb3VwZWRfY2VsbGRhdGEsIGFlcyh4ID0gbWVkX3JhbmssIHkgPSBtZWRfc3VtLCBjb2xvciA9IHBjdF9wYXNzZWQpKSArCiAgZ2VvbV9wb2ludCgKICAgIG1hcHBpbmcgPSBhZXMoeCA9IHJhbmssIHkgPSBzdW0sIGNvbG9yID0gZmlsdGVyX3BjdCksCiAgICBkYXRhID0gdG9wX2NlbGxkYXRhLAogICAgYWxwaGEgPSAwLjUKICApICsKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMiwgbGluZWVuZCA9ICJyb3VuZCIsIGxpbmVqb2luID0gInJvdW5kIikgKwogIHNjYWxlX3hfbG9nMTAobGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoYWNjdXJhY3kgPSAxKSkgKwogIHNjYWxlX3lfbG9nMTAobGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoYWNjdXJhY3kgPSAxKSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50MigKICAgIGxvdyA9ICJncmV5NzAiLAogICAgbWlkID0gImZvcmVzdGdyZWVuIiwKICAgIGhpZ2ggPSAiZGFya2dyZWVuIiwKICAgIG1pZHBvaW50ID0gNTAKICApICsKICBsYWJzKAogICAgeCA9ICJSYW5rIiwKICAgIHkgPSAiVG90YWwgVU1JIGNvdW50IiwKICAgIGNvbG9yID0gIiUgcGFzc2luZ1xuY2VsbCBmaWx0ZXIiCiAgKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAsIDApLAogICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsIDApLAogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiZ3JleTIwIiwgbGluZXdpZHRoID0gMC4yNSksCiAgICBsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbihyZXAoNSwgNCkpCiAgKQpgYGAKClRoZSB0b3RhbCBVTUkgY291bnQgb2YgZWFjaCBkcm9wbGV0IChiYXJjb2RlKSBwbG90dGVkIGFnYWluc3QgdGhlIHJhbmsgb2YgdGhhdCBkcm9wbGV0IGFsbG93cyB2aXN1YWxpemF0aW9uIG9mIHRoZSBkaXN0cmlidXRpb24gb2Ygc2VxdWVuY2luZyBkZXB0aCBhY3Jvc3MgZHJvcGxldHMuClRoZSBkcm9wbGV0cyB0aGF0IGFyZSBleHBlY3RlZCB0byBjb250YWluIGNlbGxzIHdlcmUgaWRlbnRpZmllZCB3aXRoIFtgRHJvcGxldFV0aWxzOjplbXB0eURyb3BzQ2VsbFJhbmdlcigpYF0oaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2UvYmlvYy9odG1sL0Ryb3BsZXRVdGlscy5odG1sKSwgdW5sZXNzIG90aGVyd2lzZSBzcGVjaWZpZWQgaW4gdGhlIGBDZWxsIFN0YXRpc3RpY3NgIHRhYmxlLCB3aGljaCB1c2VzIGJvdGggdGhlIHRvdGFsIFVNSSBjb3VudHMgYW5kIGV4cHJlc3NlZCBnZW5lIGNvbnRlbnQgKGFkYXB0ZWQgZnJvbSBbTHVuICBfZXQgYWwuXyAyMDE5XShodHRwczovL2RvaS5vcmcvMTAuMTE4Ni9zMTMwNTktMDE5LTE2NjIteSkpLgpBcyB0aGUgYm91bmRhcnkgYmV0d2VlbiBkcm9wbGV0cyBwYXNzaW5nIGFuZCBmYWlsaW5nIHRoaXMgZmlsdGVyIGlzIG5vdCBzb2xlbHkgZGVwZW5kZW50IG9uIHRvdGFsIFVNSSBjb3VudCwgc29tZSByZWdpb25zIGNvbnRhaW4gZHJvcGxldHMgaW4gYm90aCBjYXRlZ29yaWVzLgpUaGUgY29sb3IgaW4gdGhpcyBwbG90IGluZGljYXRlcyB0aGUgcGVyY2VudGFnZSBvZiBkcm9wbGV0cyBpbiBhIHJlZ2lvbiBwYXNzaW5nIHRoZSBmaWx0ZXIuCgojIyBDZWxsIFJlYWQgTWV0cmljcwoKYGBge3IsIGZpZy5hbHQ9IlRvdGFsIFVNSSB4IGdlbmVzIGV4cHJlc3NlZCJ9CmZpbHRlcmVkX2NlbGxkYXRhIDwtIGRhdGEuZnJhbWUoY29sRGF0YShmaWx0ZXJlZF9zY2UpKQoKZ2dwbG90KAogIGZpbHRlcmVkX2NlbGxkYXRhLAogIGFlcygKICAgIHggPSBzdW0sCiAgICB5ID0gZGV0ZWN0ZWQsCiAgICBjb2xvciA9IHN1YnNldHNfbWl0b19wZXJjZW50CiAgKQopICsKICBnZW9tX3BvaW50KGFscGhhID0gMC4zKSArCiAgc2NhbGVfY29sb3JfdmlyaWRpc19jKGxpbWl0cyA9IGMoMCwgMTAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX251bWJlcihhY2N1cmFjeSA9IDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6bGFiZWxfbnVtYmVyKGFjY3VyYWN5ID0gMSkpICsKICBsYWJzKAogICAgeCA9ICJUb3RhbCBVTUkgY291bnQiLAogICAgeSA9ICJOdW1iZXIgb2YgZ2VuZXMgZGV0ZWN0ZWQiLAogICAgY29sb3IgPSAiUGVyY2VudCByZWFkc1xubWl0b2Nob25kcmlhbCIKICApICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMCwgMSksCiAgICBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwgMSksCiAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJncmV5MjAiLCBsaW5ld2lkdGggPSAwLjI1KSwKICAgIGxlZ2VuZC5ib3gubWFyZ2luID0gbWFyZ2luKHJlcCg1LCA0KSkKICApCmBgYAoKVGhlIGFib3ZlIHBsb3Qgb2YgY2VsbCBtZXRyaWNzIGluY2x1ZGVzIG9ubHkgZHJvcGxldHMgd2hpY2ggaGF2ZSBwYXNzZWQgdGhlIGBlbXB0eURyb3BzQ2VsbFJhbmdlcigpYCBmaWx0ZXIuClRoZSBwbG90IHdpbGwgdXN1YWxseSBkaXNwbGF5IGEgc3Ryb25nIChidXQgY3VydmVkKSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdG90YWwgVU1JIGNvdW50IGFuZCB0aGUgbnVtYmVyIG9mIGdlbmVzIGRldGVjdGVkLgpDZWxscyB3aXRoIGxvdyBVTUkgY291bnRzIGFuZCBoaWdoIG1pdG9jaG9uZHJpYWwgcGVyY2VudGFnZXMgbWF5IHJlcXVpcmUgZnVydGhlciBmaWx0ZXJpbmcuCgojIyBtaVFDIE1vZGVsIERpYWdub3N0aWNzCgpgYGB7ciwgZmlnLmFsdD0ibWlRQyBtb2RlbCBkaWFnbm9zdGljcyBwbG90IiwgcmVzdWx0cz0nYXNpcycsIHdhcm5pbmc9RkFMU0V9CmlmIChza2lwX21pUUMpIHsKICBjYXQoIm1pUUMgbW9kZWwgbm90IGNyZWF0ZWQsIHNraXBwaW5nIG1pUUMgcGxvdC4gVXN1YWxseSB0aGlzIGlzIGJlY2F1c2UgbWl0b2Nob25kcmlhbCBnZW5lIGRhdGEgd2FzIG5vdCBhdmFpbGFibGUuIikKfSBlbHNlIHsKICAjIHJlbW92ZSBwcm9iX2NvbXByb21pc2VkIGlmIGl0IGV4aXN0cywgYXMgdGhpcyB3aWxsIGNhdXNlIGVycm9ycyB3aXRoIHBsb3RNb2RlbAogIGZpbHRlcmVkX3NjZSRwcm9iX2NvbXByb21pc2VkIDwtIE5VTEwKICBtaVFDX21vZGVsIDwtIG1ldGFkYXRhKGZpbHRlcmVkX3NjZSkkbWlRQ19tb2RlbAoKICBpZiAoaXMubnVsbChtaVFDX21vZGVsKSB8fCBsZW5ndGgobWlRQ19tb2RlbEBjb21wb25lbnRzKSA8IDIpIHsKICAgICMgbW9kZWwgZGlkbid0IGZpdCwganVzdCBwbG90IG1ldHJpY3MKICAgIG1pUUNfcGxvdCA8LSBtaVFDOjpwbG90TWV0cmljcyhmaWx0ZXJlZF9zY2UpCiAgfSBlbHNlIHsKICAgIG1pUUNfcGxvdCA8LSBtaVFDOjpwbG90TW9kZWwoZmlsdGVyZWRfc2NlLCBtb2RlbCA9IG1pUUNfbW9kZWwpCiAgICAjIHNldCBsaW5lIHRoaWNrbmVzcwogICAgbGluZV9hZXMgPC0gbGlzdChsaW5ld2lkdGggPSAxLCBhbHBoYSA9IDAuOCkKICAgIG1pUUNfcGxvdCRsYXllcnNbWzJdXSRhZXNfcGFyYW1zIDwtIGxpbmVfYWVzCiAgICBtaVFDX3Bsb3QkbGF5ZXJzW1szXV0kYWVzX3BhcmFtcyA8LSBsaW5lX2FlcwogIH0KCiAgbWlRQ19wbG90ICsKICAgIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLCAxMDApKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoYWNjdXJhY3kgPSAxKSkgKwogICAgbGFicygKICAgICAgeCA9ICJOdW1iZXIgb2YgZ2VuZXMgZGV0ZWN0ZWQiLAogICAgICB5ID0gIlBlcmNlbnQgcmVhZHMgbWl0b2Nob25kcmlhbCIKICAgICkgKwogICAgdGhlbWUoCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMSwgMSksCiAgICAgIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygxLCAxKSwKICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiZ3JleTIwIiwgbGluZXdpZHRoID0gMC4yNSksCiAgICAgIGxlZ2VuZC5ib3gubWFyZ2luID0gbWFyZ2luKHJlcCg1LCA0KSkKICAgICkKfQpgYGAKCldlIGNhbGN1bGF0ZSB0aGUgcHJvYmFiaWxpdHkgdGhhdCBhIGNlbGwgaXMgY29tcHJvbWlzZWQgZHVlIHRvIGRlZ3JhZGF0aW9uIG9yIHJ1cHR1cmUgdXNpbmcgW2BtaVFDYF0oaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2UvYmlvYy9odG1sL21pUUMuaHRtbCkgKFtIaXBwZW4gX2V0IGFsLl8gMjAyMV0oaHR0cHM6Ly9kb2kub3JnLzEwLjEzNzEvam91cm5hbC5wY2JpLjEwMDkyOTApKS4KVGhpcyByZWxpZXMgb24gZml0dGluZyBhIG1peHR1cmUgbW9kZWwgdXNpbmcgdGhlIG51bWJlciBvZiBnZW5lcyBleHByZXNzZWQgYnkgYSBjZWxsIGFuZCB0aGUgcGVyY2VudGFnZSBvZiBtaXRvY2hvbmRyaWFsIHJlYWRzLgpUaGUgZXhwZWN0ZWQgcGxvdCB3aWxsIHNob3cgYSBjaGFyYWN0ZXJpc3RpYyB0cmlhbmd1bGFyIHNoYXBlIGFuZCB0d28gbW9kZWwgZml0IGxpbmVzLgpDZWxscyB3aXRoIGxvdyBudW1iZXJzIG9mIGdlbmVzIGV4cHJlc3NlZCBtYXkgaGF2ZSBib3RoIGxvdyBhbmQgaGlnaCBtaXRvY2hvbmRyaWFsIHBlcmNlbnRhZ2UsIGJ1dCBjZWxscyB3aXRoIG1hbnkgZ2VuZXMgdGVuZCB0byBoYXZlIGEgbG93IG1pdG9jaG9uZHJpYWwgcGVyY2VudGFnZS4KQ29tcHJvbWlzZWQgY2VsbHMgYXJlIGxpa2VseSB0byBoYXZlIGEgZmV3ZXIgZ2VuZXMgZGV0ZWN0ZWQgYW5kIGhpZ2hlciBwZXJjZW50YWdlIG9mIG1pdG9jaG9uZHJpYWwgcmVhZHMuCgpJZiB0aGUgbW9kZWwgaGFzIGZhaWxlZCB0byBmaXQgcHJvcGVybHksIHRoZSBwYXR0ZXJuIG9mIGNlbGxzIG1heSBkaWZmZXIsIGFuZCB0aGVyZSBtYXkgbm90IGJlIG1vZGVsIGZpdCBsaW5lcy4KVGhpcyBjYW4gYmUgdGhlIHJlc3VsdCBvZiBhIGxvdy1xdWFsaXR5IGxpYnJhcnkgb3IgbWF5IG9jY3VyIGlmIHRoZXJlIGlzIG5vIG1pdG9jaG9uZHJpYWwgY29udGVudCwgYXMgaW4gdGhlIGNhc2Ugb2YgYSBoaWdoLXF1YWxpdHkgc2luZ2xlLW51Y2xldXMgc2FtcGxlLgpJbiBzdWNoIHNpdHVhdGlvbnMsIHRoZSBjYWxjdWxhdGVkIHByb2JhYmlsaXR5IG9mIGNvbXByb21pc2UgbWF5IG5vdCBiZSB2YWxpZCAoc2VlIFttaVFDIHZpZ25ldHRlXShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvMy4xMy9iaW9jL3ZpZ25ldHRlcy9taVFDL2luc3QvZG9jL21pUUMuaHRtbCN3aGVuLW5vdC10by11c2UtbWlxYykgZm9yIG1vcmUgZGV0YWlscykuCgojIyBSZW1vdmluZyBsb3cgcXVhbGl0eSBjZWxscwoKVGhlIGJlbG93IHBsb3QgaGlnaGxpZ2h0cyBjZWxscyB0aGF0IHdlcmUgcmVtb3ZlZCBwcmlvciB0byBub3JtYWxpemF0aW9uIGFuZCBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24uCkNlbGxzIHRoYXQgc2hvdWxkIGJlIHJlbW92ZWQgYmFzZWQgb24gUk5BIGNvdW50cyBhcmUgdGhvc2UgdGhhdCBhcmUgaWRlbnRpZmllZCB0byBiZSBsb3cgcXVhbGl0eSBjZWxscywgc3VjaCBhcyBjZWxscyB3aXRoIGhpZ2ggcHJvYmFiaWxpdHkgb2YgYmVpbmcgY29tcHJvbWlzZWQuClRoZSBtZXRob2Qgb2YgZmlsdGVyaW5nIGlzIGluZGljYXRlZCBhYm92ZSB0aGUgcGxvdCBhcyBlaXRoZXIgYG1pUUNgIG9yIGBNaW5pbXVtIGdlbmUgY3V0b2ZmYC4KSWYgYG1pUUNgLCBjZWxscyBiZWxvdyB0aGUgc3BlY2lmaWVkIHByb2JhYmlsaXR5IGNvbXByb21pc2VkIGN1dG9mZiBhbmQgYWJvdmUgdGhlIG1pbmltdW0gbnVtYmVyIG9mIHVuaXF1ZSBnZW5lcyBpZGVudGlmaWVkIGFyZSBrZXB0IGZvciBkb3duc3RyZWFtIGFuYWx5c2VzLgpJZiBvbmx5IGEgYE1pbmltdW0gZ2VuZSBjdXRvZmZgIGlzIHVzZWQsIHRoZW4gYG1pUUNgIGlzIG5vdCB1c2VkIGFuZCBvbmx5IHRob3NlIGNlbGxzIHRoYXQgcGFzcyB0aGUgbWluaW11bSBudW1iZXIgb2YgdW5pcXVlIGdlbmVzIGlkZW50aWZpZWQgdGhyZXNob2xkIGFyZSByZXRhaW5lZC4KVGhlIGRvdHRlZCB2ZXJ0aWNhbCBsaW5lIGluZGljYXRlcyB0aGUgbWluaW11bSBnZW5lIGN1dG9mZiB1c2VkIGZvciBmaWx0ZXJpbmcuCgoKYGBge3IgcmVzdWx0cz0nYXNpcyd9CmlmIChoYXNfZmlsdGVyZWQgJiYgaGFzX3Byb2Nlc3NlZCkgewogICMgZ3JhYiBjdXRvZmZzIGFuZCBmaWx0ZXJpbmcgbWV0aG9kIGZyb20gcHJvY2Vzc2VkIHNjZQogIG1pbl9nZW5lX2N1dG9mZiA8LSBwcm9jZXNzZWRfbWV0YSRtaW5fZ2VuZV9jdXRvZmYKCiAgZmlsdGVyX21ldGhvZCA8LSBwcm9jZXNzZWRfbWV0YSRzY3BjYV9maWx0ZXJfbWV0aG9kCgogICMgYWRkIGNvbHVtbiB0byBjb2xkYXRhIGxhYmVsaW5nIGNlbGxzIHRvIGtlZXAvcmVtb3ZlIGJhc2VkIG9uIGZpbHRlcmluZyBtZXRob2QKICBmaWx0ZXJlZF9jb2xkYXRhX2RmIDwtIGNvbERhdGEoZmlsdGVyZWRfc2NlKSB8PgogICAgYXMuZGF0YS5mcmFtZSgpIHw+CiAgICB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbigiYmFyY29kZSIpCgogIGdncGxvdChmaWx0ZXJlZF9jb2xkYXRhX2RmLCBhZXMoeCA9IGRldGVjdGVkLCB5ID0gc3Vic2V0c19taXRvX3BlcmNlbnQsIGNvbG9yID0gc2NwY2FfZmlsdGVyKSkgKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1pbl9nZW5lX2N1dG9mZiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgbGFicygKICAgICAgeCA9ICJOdW1iZXIgb2YgZ2VuZXMgZGV0ZWN0ZWQiLAogICAgICB5ID0gIk1pdG9jaG9uZHJpYWwgcGVyY2VudGFnZSIsCiAgICAgIGNvbG9yID0gIkZpbHRlciIsCiAgICAgIHRpdGxlID0gc3RyaW5ncjo6c3RyX3JlcGxhY2UoZmlsdGVyX21ldGhvZCwgIl8iLCAiICIpCiAgICApICsKICAgIHRoZW1lKAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygxLCAxKSwKICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsIDEpLAogICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJncmV5MjAiLCBsaW5ld2lkdGggPSAwLjI1KSwKICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KQogICAgKQp9IGVsc2UgewogIGdsdWU6OmdsdWUoIgogICAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXdhcm5pbmdcIj4KCiAgICBObyBmaWx0ZXJpbmcgb2YgbG93IHF1YWxpdHkgY2VsbHMgd2FzIHBlcmZvcm1lZCBvbiB0aGlzIGxpYnJhcnkuCgogICAgPC9kaXY+CiAgIikKfQpgYGAKClRoZSByYXcgY291bnRzIGZyb20gYWxsIGNlbGxzIHRoYXQgcmVtYWluIGFmdGVyIGZpbHRlcmluZyBsb3cgcXVhbGl0eSBjZWxscyAoUk5BIG9ubHkpIGFyZSB0aGVuIG5vcm1hbGl6ZWQgcHJpb3IgdG8gc2VsZWN0aW9uIG9mIGhpZ2hseSB2YXJpYWJsZSBnZW5lcyBhbmQgZGltZW5zaW9uYWxpdHkgcmVkdWN0aW9uLgoKCgo8IS0tIE5leHQgc2VjdGlvbiBpbmNsdWRlIG9ubHkgaWYgVU1BUCBpcyBwcmVzZW50IC0tPgpgYGB7ciwgY2hpbGQ9J3VtYXBfcWMucm1kJywgZXZhbCA9IGhhc191bWFwfQpgYGAKCjwhLS0gTmV4dCBzZWN0aW9uIGluY2x1ZGVkIG9ubHkgaWYgQ0lURS1zZXEgZGF0YSBpcyBwcmVzZW50IC0tPgpgYGB7ciwgY2hpbGQ9J2NpdGVfcWMucm1kJywgZXZhbCA9IGhhc19hZHR9CmBgYAoKPCEtLSBOZXh0IHNlY3Rpb24gb25seSBpbmNsdWRlZCBpZiBtdWx0aXBsZXggZGF0YSBpcyBwcmVzZW50IC0tPgpgYGB7ciwgY2hpbGQ9J211bHRpcGxleF9xYy5ybWQnLCBldmFsID0gaGFzX2NlbGxoYXNofQpgYGAKCjwhLS0gTmV4dCBzZWN0aW9ucyBvbmx5IGluY2x1ZGVkIGlmIGNlbGx0eXBlIGFubm90YXRpb25zIGFyZSBwcmVzZW50IC0tPgpgYGB7ciwgY2hpbGQ9J3V0aWxzL2NlbGx0eXBlX2Z1bmN0aW9ucy5ybWQnLCBldmFsID0gaGFzX2NlbGx0eXBlc30KYGBgCgpgYGB7ciwgY2hpbGQ9J2NlbGx0eXBlc19xYy5ybWQnLCBldmFsID0gaGFzX2NlbGx0eXBlc30KYGBgCgoKIyBTZXNzaW9uIEluZm8KPGRldGFpbHM+CjxzdW1tYXJ5PlIgc2Vzc2lvbiBpbmZvcm1hdGlvbjwvc3VtbWFyeT4KYGBge3Igc2Vzc2lvbl9pbmZvfQppZiAocmVxdWlyZU5hbWVzcGFjZSgic2Vzc2lvbmluZm8iLCBxdWlldGx5ID0gVFJVRSkpIHsKICBzZXNzaW9uaW5mbzo6c2Vzc2lvbl9pbmZvKCkKfSBlbHNlIHsKICBzZXNzaW9uSW5mbygpCn0KYGBgCjwvZGV0YWlscz4K